package com.nekonomics
package domain.validation

import error.UserError.*

import com.nekonomics.error.{UserError, ValidationError}
import com.nekonomics.error.ValidationError.*
import com.nekonomics.utils.PasswordUtil
import zio.*


object UserValidator {

  private val EmailRegex = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$".r
  private val LetterAndDigitRegex = "^[a-zA-Z0-9_]+$".r
  private val MinPasswordLength = 6
  private val MaxNicknameLength = 20
  private lazy val  success = ZIO.succeed(())


  private def isStrLetterOrDigit(s: String) = LetterAndDigitRegex.matches(s)
  
  def validatePassword(passwordHash: String, passwordFromReq: String): IO[UserError, Unit] = {
    val hash = PasswordUtil.hash(passwordFromReq)
    if hash != passwordHash then 
      ZIO.fail(IncorrectPassword)
    else
      success
  }
  
  def validate(email: String, password: String, nickname: String): IO[ValidationError, Unit] = {
    for {
      _ <- validateEmail(email)
      _ <- validatePassword(password)
      _ <- validateNickname(nickname)
    } yield ()
  }

  def validateEmail(email: String): IO[ValidationError, Unit] =
    if email.trim.isEmpty then
      ZIO.fail(EmptyField("邮件"))
    else if !EmailRegex.matches(email) then
      ZIO.fail(InvalidEmail)
    else success

  def validatePassword(password: String): IO[ValidationError, Unit] =
    if password.trim.isEmpty then
      ZIO.fail(EmptyField("密码"))
    else if !isStrLetterOrDigit(password) then
      ZIO.fail(SpecialSymbol)
    else if password.length < MinPasswordLength then
      ZIO.fail(InvalidLength(s"密码长度至少为$MinPasswordLength"))
    else success


  def validateNickname(nickname: String): IO[ValidationError, Unit] =
    if nickname.trim.isEmpty then
      ZIO.fail(EmptyField("昵称"))
    else if !isStrLetterOrDigit(nickname) then
      ZIO.fail(SpecialSymbol)
    else if nickname.length > MaxNicknameLength then
      ZIO.fail(InvalidLength(s"昵称长度不能大于$MaxNicknameLength"))
    else success

  
}

